package com.le.sarrs.util;

import com.google.common.base.Splitter;
import org.apache.log4j.Logger;

import javax.servlet.http.HttpServletRequest;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class Utils {
    private static Logger logger = Logger.getLogger(Utils.class);

    private static Map<String, String> headers = new HashMap<>();

    static {
        headers.put("ipH1", "X-Real-IP");
        headers.put("ipH2", "x-forwarded-for");
        headers.put("ipH3", "X-Forwarded-For");
        headers.put("ipH4", "Proxy-Client-IP");
        headers.put("ipH5", "WL-Proxy-Client-IP");
    }

    private static String clientIp(HttpServletRequest request) {
        String ip = "";
        if (!isInner(request.getRemoteAddr())) {
            ip = request.getRemoteAddr();
            return ip;
        }
        for (int i = 1; i <= headers.size(); i++) {
            String ips = request.getHeader(headers.get("ipH" + i));
            if (ips != null && ips.length() != 0 && (!"unknown".equalsIgnoreCase(ips))) {
                logger.info("initip=" + ips);
                if (ips.contains(",")) {
                    Splitter splitter = Splitter.on(',').trimResults().omitEmptyStrings();
                    List<String> ipList = splitter.splitToList(ips);
                    for (String aip : ipList) {
                        if (!isInner(aip)) {
                            ip = aip;
                            break;
                        }
                    }
                } else {
                    if (!isInner(ips)) {
                        ip = ips;
                        break;
                    }
                }
            }
        }
        return ip;
    }

    public static String getIpAddr(HttpServletRequest request) {
        return clientIp(request);

    }

    /**
     * check inner ip
     */
    private static boolean isInner(String ip) {
        String reg = "(10|172|192)\\.([0-1][0-9]{0,2}|[2][0-5]{0,2}|[3-9][0-9]?)\\.([0-1][0-9]{0,2}|[2][0-5]{0,2}|[3-9][0-9]?)\\.([0-1][0-9]{0,2}|[2][0-5]{0,2}|[3-9][0-9]?)";//正则表达式
        Pattern p = Pattern.compile(reg);
        Matcher matcher = p.matcher(ip);
        return matcher.find();
    }


    /**
     * 判断是否为合法IP
     */
    private static boolean islIp(String ipAddress) {
        if (null == ipAddress) {
            return false;
        }
        String ip = "\\b((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\.((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\.((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\.((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\b";
        Pattern pattern = Pattern.compile(ip);
        Matcher matcher = pattern.matcher(ipAddress);
        return matcher.matches();
    }

    private static boolean isLocalIp(String ip) {
        boolean flag = false;
        if (null != ip && (ip.contains("192.168") || ip.contains("10.") || ip.contains("172.16"))) {
            flag = true;
        }
        return flag;
    }

    public static String encodeUrlMD5(String s) {
        char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                'a', 'b', 'c', 'd', 'e', 'f'};
        try {
            byte[] strTemp = s.getBytes();
            MessageDigest mdTemp = MessageDigest.getInstance("MD5");
            mdTemp.update(strTemp);
            byte[] md = mdTemp.digest();
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (byte byte0 : md) {
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            return null;
        }
    }

    public static String log(String uid, String lc, HttpServletRequest request, final String... values) {
        StringBuilder log = new StringBuilder();
        log.append(uid);
        log.append("|");
        log.append(lc);
        log.append("|");
        log.append(getCurrentDate());
        log.append("|");
        log.append(getIpAddr(request));
        if (values != null) {
            for (String value : values) {
                log.append("|");
                log.append(value);
            }
        }
        return log.toString();
    }

    /***
     * 乐见日志标准    classname|time|user|ip|date|url|others
     *
     * @param time    耗时
     * @param user    当前用户
     * @param request request
     * @param url     请求url
     * @param values  其他值
     * @return log
     */
    public static String log(String classname, long time, String user, HttpServletRequest request, String url, final String... values) {
        StringBuilder log = new StringBuilder();
        log.append("stat=")
                .append(classname)
                .append("|")
                .append(time)
                .append("|")
                .append(user)
                .append("|")
                .append(Utils.getIpAddr(request))
                .append("|")
                .append(getCurrentDate())
                .append("|")
                .append(url);
        if (values != null) {
            for (String value : values) {
                log.append("|");
                log.append(value);
            }
        }
        return log.toString();
    }

    public static String log(String uid, long lc, final String... values) {
        StringBuilder log = new StringBuilder();
        log.append(uid);
        log.append("|");
        log.append(lc);
        log.append("|");
        log.append(getCurrentDate());
        log.append("|");
        if (values != null) {
            for (String value : values) {
                log.append("|");
                log.append(value);
            }
        }
        return log.toString();
    }

    /**
     * 获得当前时间，格式yyyy-MM-dd hh:mm:ss
     *
     * @return yyyy-MM-dd hh:mm:ss
     */
    public static String getCurrentDate() {
        return DateUtil.getCurrentDate("yyyy-MM-dd HH:mm:ss");
    }

    public static boolean isInnerIP(String ipAddress) {
        boolean isInnerIp;
        long ipNum = getIpNum(ipAddress);
        /**
         私有IP：A类  10.0.0.0-10.255.255.255
         B类  172.16.0.0-172.31.255.255
         C类  192.168.0.0-192.168.255.255
         当然，还有127这个网段是环回地址
         **/
        long aBegin = getIpNum("10.0.0.0");
        long aEnd = getIpNum("10.255.255.255");
        long bBegin = getIpNum("172.16.0.0");
        long bEnd = getIpNum("172.31.255.255");
        long cBegin = getIpNum("192.168.0.0");
        long cEnd = getIpNum("192.168.255.255");
        System.out.println(aBegin + "|" + aEnd + "|" + bBegin + "|" + bEnd + "|" + cBegin + "|" + cEnd + "|");
        isInnerIp = isInner(ipNum, aBegin, aEnd) || isInner(ipNum, bBegin, bEnd) || isInner(ipNum, cBegin, cEnd) || ipAddress.equals("127.0.0.1");
        return isInnerIp;
    }

    private static long getIpNum(String ipAddress) {
        String[] ip = ipAddress.split("\\.");
        long a = Integer.parseInt(ip[0]);
        long b = Integer.parseInt(ip[1]);
        long c = Integer.parseInt(ip[2]);
        long d = Integer.parseInt(ip[3]);

        return a * 256 * 256 * 256 + b * 256 * 256 + c * 256 + d;
    }

    private static boolean isInner(long userIp, long begin, long end) {
        return (userIp >= begin) && (userIp <= end);
    }

}
